package com.ocm.core.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.ocm.core.domain.ClassDefinition;
import com.ocm.core.domain.PropertyDefinition;
import com.ocm.core.dto.GroupDto;
import com.ocm.core.dto.PropertyDefinitionDto;
import com.ocm.core.dto.PropertyValueDto;
import com.ocm.core.dto.UserInfoDto;
import com.ocm.core.exception.UnsupportTypeException;

public class OCMUtil {

   public static Map<PropertyDefinition, Object> convertFromProperyDefs(List<PropertyValueDto> propertiesValue, List<PropertyDefinition> propertyDefs) throws UnsupportTypeException {
      Map<PropertyDefinition, Object> results = new HashMap<PropertyDefinition, Object>();
      for (PropertyValueDto propertyValueDto : propertiesValue) {
         PropertyDefinitionDto propertyDefinition = propertyValueDto.getProperty();
         PropertyDefinition actualPropertyDef = getPropertyDefinition(propertyDefinition.getId(), propertyDefs);
         results.put(actualPropertyDef, propertyValueDto.getValue());
      }
      return results;
   }

   public static Map<PropertyDefinition, Object> convertFromProperyDefs(Map<String, Object> propertiesValue, List<PropertyDefinition> propertyDefs) throws UnsupportTypeException {
      Map<PropertyDefinition, Object> results = new HashMap<PropertyDefinition, Object>();
      for (PropertyDefinition propertyDefinition : propertyDefs){
         String propertyName = propertyDefinition.getName();
         if (propertiesValue.containsKey(propertyName)){
            results.put(propertyDefinition, propertiesValue.get(propertyName));
         }
      }
      return results;
   }

   public static List<PropertyValueDto> convertFromProperyValues(Map<PropertyDefinition, Object> propertyValues, List<PropertyDefinitionDto> propertyDefDtos) {
      List<PropertyValueDto> properties = new ArrayList<PropertyValueDto>();
      for (Iterator<PropertyDefinition> it = propertyValues.keySet().iterator(); it.hasNext();) {
         PropertyDefinition propertyDefinition = it.next();
         PropertyDefinitionDto propertyDefinitionDto = getPropertyDefinitionDto(propertyDefinition.getId(), propertyDefDtos);
         PropertyValueDto propertyValueDto = new PropertyValueDto();
         propertyValueDto.setProperty(propertyDefinitionDto);
         propertyValueDto.setValue(propertyValues.get(propertyDefinition));
         properties.add(propertyValueDto);
      }
      return properties;
   }

   public static ClassDefinition getClassDefinition(String name, List<ClassDefinition> classDefs) {
      for (ClassDefinition classDefinition : classDefs) {
         if (classDefinition.getName().equalsIgnoreCase(name)){
            return classDefinition;
         }
      }
      return null;
   }

   public static PropertyDefinition getPropertyDefinition(String name, List<PropertyDefinition> properties) {
      for (PropertyDefinition property : properties) {
         if (property.getName().equalsIgnoreCase(name)){
            return property;
         }
      }
      return null;
   }


   public static PropertyDefinitionDto getPropertyDefinitionDto(String name, List<PropertyDefinitionDto> properties) {
      for (PropertyDefinitionDto property : properties) {
         if (property.getName().equalsIgnoreCase(name)){
            return property;
         }
      }
      return null;
   }

   public static List<PropertyDefinition> getPropertyDefinition(String[] names, List<PropertyDefinition> properties) {
      List<PropertyDefinition> expectedProperties = new ArrayList<PropertyDefinition>();
      for (PropertyDefinition property : properties) {
         for (String name : names){
            if (property.getName().equalsIgnoreCase(name)){
               expectedProperties.add(property);
               break;
            }
         }
      }
      return expectedProperties;
   }

   public static List<PropertyDefinition> getPropertyDefinitions(String[] excludeNames, List<PropertyDefinition> propertyDefs){
      if (excludeNames.length > 0){
         List<PropertyDefinition> newProperties = new ArrayList<PropertyDefinition>(propertyDefs);
         for (String exclude : excludeNames){
            PropertyDefinition actual = getPropertyDefinition(exclude, newProperties);
            if (actual != null){
               newProperties.remove(actual);
            }
         }
         return newProperties;
      }
      return propertyDefs;
   }

   public static PropertyDefinition getPropertyDefinition(Long propertyId, List<PropertyDefinition> propertyDefs){
      PropertyDefinition expectedPropertyDef = new PropertyDefinition();
      expectedPropertyDef.setId(propertyId);
      PropertyDefinition actualPropertyDef = null;
      if (propertyDefs.contains(expectedPropertyDef))
        actualPropertyDef = propertyDefs.get(propertyDefs.indexOf(expectedPropertyDef));
        
      return actualPropertyDef;
   }

   public static PropertyDefinitionDto getPropertyDefinitionDto(Long propertyId, List<PropertyDefinitionDto> propertyDefs){
      PropertyDefinitionDto expectedPropertyDef = new PropertyDefinitionDto();
      expectedPropertyDef.setId(propertyId);
      PropertyDefinitionDto actualPropertyDef = propertyDefs.get(propertyDefs.indexOf(expectedPropertyDef));
      return actualPropertyDef;
   }
   
   public static UserInfoDto getUserInfoDto(Long userId, List<UserInfoDto> userInfoDtos){
      UserInfoDto userInfoDto = new UserInfoDto();
      userInfoDto.setId(userId);
      int index = userInfoDtos.indexOf(userInfoDto);
      UserInfoDto actualUser = null;
      if (index >= 0)
         actualUser = userInfoDtos.get(index);
      return actualUser;
   }
   
   public static String getAuthorities(List<GroupDto> groupDtos){
      String result = "";
      for (GroupDto groupDto : groupDtos){
         String authorities = groupDto.getAuthority();
         if (result.indexOf(authorities) < 0){
            result=result.concat(authorities + ",");
         }
      }
      if (!("".equals(result))){
         result = result.substring(0, result.length() - 1);
      }
      return result;
   }
}
